#ifndef VICSEK_H
#define VICSEK_H
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<string.h>
using namespace std;
class Vicsek
{
public:
	float *x, *y;
	float *vx, *vy;
	int *c, *cs;
	int **clist; //clist maintain the list of ids in each cell.
	int **pclist;
	int **palist;
	int *pasize;
	int* nlist;  //K*N;
	float* CF;
	float* AF;
	float* NF;

	int N;
	int K;
	float L;
	int M; //M*M grids;
public:

	Vicsek(int n, int k, float l, int m);

	void Init();
	//allocate space for x,y,vx,vy,c,cs,set initial values for x,y,vx,vy;
    void ClearMemory();

	void Hash_mapping();
	//given x,y set values of c, cs. allocate space for clist. and set values for clist;

	void Get_Potential_Cell_List();

	void Get_Potential_Agent_List();

	void Find_Kth_Min(float* data, int n, int k, int* index);

	void Search_K_Neighbors();

	void Get_Alignment_Force();

	void Get_Cohesion_Force();

	void Get_Noise_Force();

	void Add_Intrinsic_Noise( float );

	void Update_Speed(float, float ,float);

	void Update_Position();

	void Simulate(float, float, float);



public: // for test use only. Deleted after the program is done.

	void CreateFile(int, int, int);

	void CreateParFile(int, float, float, float);

	void test_clist()
	{
		for (int i = 0; i < M*M; i++)
			{for (int j = 0; j < cs[i]; j++)
			cout<<clist[i][j]<<" ";
		cout<<endl;}
	}

	void test_x()
	{
		for (int i = 0; i < N; i++)
		{
			cout<<x[i]<<" "<<y[i]<<endl;
		}
	}
	void test_vx()
	{
		for (int i = 0; i < N; i++)
		{
			cout<<sqrt(vx[i]*vx[i] + vy[i]*vy[i])<<" "<<endl;
			//cout<<vx[i]<<" "<<vy[i]<<endl;
		}
	}

	void test_csize()
	{
		for (int i = 0; i < M*M; i++)
			cout<<cs[i]<<endl;
	}

	void test_pclist()
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < 25; j++)
				cout<<pclist[i][j]<<" ";
			cout<<endl;
		}
	}
	void test_palist()
	{
		for (int i = 0; i < N; i++)
		{
			cout<<pasize[i]<<endl;
			for (int j = 0; j < pasize[i]; j++)
				cout<<palist[i][j]<<" ";
			cout<<endl;
		}
	}
	void test_nlist()
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < K; j++)
				cout<<nlist[i*K+j]<<" ";
			cout<<endl;
		}
	}
	void test_AF()
	{
		for (int i = 0; i < N; i++)
			{cout<<sqrt(AF[2*i]*AF[2*i]+AF[2*i+1]*AF[2*i+1])<<" ";
		cout<<AF[2*i]<<" "<<AF[2*i+1]<<endl;}
	}
	void test_CF()
	{
		for (int i = 0; i < N; i++)
			{cout<<sqrt(CF[2*i]*CF[2*i]+CF[2*i+1]*CF[2*i+1])<<" ";
			cout<<CF[2*i]<<" "<<CF[2*i+1]<<endl;
		}
	}
	void test_NF()
	{
		for (int i = 0; i < N; i++)
			{cout<<sqrt(NF[2*i]*NF[2*i]+NF[2*i+1]*NF[2*i+1])<<" ";
		cout<<NF[2*i]<<" "<<NF[2*i+1]<<endl;}
	}
	void test_order()
	{
		float s1 = 0;
		float s2 = 0;
		float r = 0;
		/*#pragma  omp parallel for*/
		for (int i = 0; i < N; i++)
			{
				s1 += vx[i];
				s2 += vy[i];
				r += vx[i]*vx[i] + vy[i]*vy[i];
		}
		r /=N ;
		s1 /= N;
		s2 /= N;
		cout<<sqrt(s1*s1+s2*s2)/ sqrt(r)<<endl;
	}
};

int CreateFolder(int );
#endif

